package cn.iocoder.yudao.module.iot.controller.app.device;

import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceControlReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceThresholdReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceRadarReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelParam;
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService;
import org.springframework.security.access.prepost.PreAuthorize;
import cn.iocoder.yudao.module.iot.controller.app.device.vo.IotAppDeviceRespVO;
import cn.iocoder.yudao.module.iot.controller.app.device.vo.IotAppDeviceControlReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService;
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
import cn.iocoder.yudao.module.iot.service.device.energy.IotDeviceEnergyService;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import org.springframework.jdbc.core.JdbcTemplate;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;

import cn.iocoder.yudao.module.iot.service.mqtt.IotMqttService;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelRespVO;

@Tag(name = "用户 APP - IoT 设备管理")
@RestController
@RequestMapping("/iot/device")
@Validated
@Slf4j
//@PreAuthorize("@ss.hasAnyUserType('MEMBER', 'ADMIN')")
public class IotAppDeviceController {

    @Resource
    private IotDeviceService deviceService;

    @Resource
    private IotProductService productService;

    @Resource
    private IotDeviceMessageService deviceMessageService;

    @Resource
    private IotDevicePropertyService devicePropertyService;

    @Resource
    private IotThingModelService thingModelService;
    @Resource
    private IotDeviceEnergyService deviceEnergyService;

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private IotMqttService iotMqttService;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @GetMapping("/list")
    @Operation(summary = "获得当前用户的设备列表")
    @TenantIgnore
    public CommonResult<List<IotAppDeviceRespVO>> getDeviceList() {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 获取设备列表请求，用户ID: {}", userId);
        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，返回空列表");
            return success(List.of());
        }
        List<IotDeviceDO> list = deviceService.getDeviceListByUserId(userId);
        log.info("[IotAppDeviceController] 获取设备列表成功，数量: {}", list.size());
        return success(BeanUtils.toBean(list, IotAppDeviceRespVO.class));
    }

    @GetMapping("/searchList")
    @Operation(summary = "搜索用户的设备列表")
    @TenantIgnore
    public CommonResult<List<IotAppDeviceRespVO>> searchList(@RequestParam("keyWord") String keyWord) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 获取设备列表请求，用户ID: {}", userId);
        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，返回空列表");
            return success(List.of());
        }
        List<IotDeviceDO> list = deviceService.getDeviceListByUserId(userId);
        if (list.isEmpty()){
            return success(List.of());
        }
        List<IotDeviceDO> res = new ArrayList<>();
        for (IotDeviceDO iotDeviceDO : list) {
            if (iotDeviceDO.getDeviceName()!=null){
                if (iotDeviceDO.getDeviceName().contains(keyWord)){
                    res.add(iotDeviceDO);
                }
            }
            if (iotDeviceDO.getNickname()!=null){
                if (iotDeviceDO.getNickname().contains(keyWord)){
                    res.add(iotDeviceDO);
                }
            }
        }

        log.info("[IotAppDeviceController] 获取设备列表成功，数量: {}", list.size());
        return success(BeanUtils.toBean(res, IotAppDeviceRespVO.class));
    }

    @GetMapping("/list-by-group")
    @Operation(summary = "获得指定分组下的设备列表")
    @Parameter(name = "groupId", description = "分组编号", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<List<IotAppDeviceRespVO>> getDeviceListByGroupId(@RequestParam("groupId") Long groupId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 获取分组设备列表请求，用户ID: {}, 分组ID: {}", userId, groupId);
        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，返回空列表");
            return success(List.of());
        }
        List<IotDeviceDO> list = deviceService.getDeviceListByGroupId(groupId);
        log.info("[IotAppDeviceController] 获取分组设备列表成功，数量: {}", list.size());
        return success(BeanUtils.toBean(list, IotAppDeviceRespVO.class));
    }

    @GetMapping("/available")
    @Operation(summary = "获得可用设备列表（未离线的设备）")
    @TenantIgnore
    public CommonResult<List<IotAppDeviceRespVO>> getAvailableDeviceList() {
        log.info("[IotAppDeviceController] 获取可用设备列表请求");
        List<IotDeviceDO> list = deviceService.getDeviceListByState(1); // 1表示在线
        log.info("[IotAppDeviceController] 获取可用设备列表成功，数量: {}", list.size());
        return success(BeanUtils.toBean(list, IotAppDeviceRespVO.class));
    }

    @GetMapping("/available-for-selection")
    @Operation(summary = "获得可供用户选择的设备列表")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getAvailableDevicesForSelection() {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 获取可供选择的设备列表请求，用户ID: {}", userId);
        
        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，返回空列表");
            return success(List.of());
        }
        
        try {
            // 获取所有在线设备
            List<IotDeviceDO> allDevices = deviceService.getDeviceListByState(1);
            
            // 获取用户已选择的设备ID列表
            String selectedDevicesSql = "SELECT device_id FROM iot_user_device WHERE user_id = ? AND deleted = 0";
            List<Long> selectedDeviceIds = jdbcTemplate.queryForList(selectedDevicesSql, Long.class, userId);
            
            // 过滤出未选择的设备
            List<Map<String, Object>> availableDevices = new ArrayList<>();
            for (IotDeviceDO device : allDevices) {
                if (!selectedDeviceIds.contains(device.getId())) {
                    Map<String, Object> deviceInfo = new HashMap<>();
                    deviceInfo.put("id", device.getId());
                    deviceInfo.put("deviceName", device.getDeviceName() != null ? device.getDeviceName() : "");
                    deviceInfo.put("nickname", device.getNickname() != null ? device.getNickname() : "");
                    deviceInfo.put("productId", device.getProductId());
                    deviceInfo.put("productKey", device.getProductKey() != null ? device.getProductKey() : "");
                    deviceInfo.put("deviceType", device.getDeviceType());
                    deviceInfo.put("state", device.getState());
                    deviceInfo.put("onlineTime", device.getOnlineTime());
                    deviceInfo.put("createTime", device.getCreateTime());
                    availableDevices.add(deviceInfo);
                }
            }
            
            log.info("[IotAppDeviceController] 获取可供选择的设备列表成功，可用设备数量: {}", availableDevices.size());
            return success(availableDevices);
            
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取可供选择的设备列表失败", e);
            return CommonResult.error(500, "获取设备列表失败：" + e.getMessage());
        }
    }

    @GetMapping("/user-device-list")
    @Operation(summary = "获取用户设备列表")
    @TenantIgnore
    public CommonResult<List<IotAppDeviceRespVO>> getUserDeviceList(@RequestParam Long userId) {
        log.info("[IotAppDeviceController] 获取用户设备列表请求，用户ID: {}", userId);

        // 查询用户在 iot_user_device 表中选择的设备
        List<IotAppDeviceRespVO> userDevices = getUserDevicesFromUserDeviceTable(userId);

        log.info("[IotAppDeviceController] 获取用户设备列表成功，数量: {}", userDevices.size());
        return success(userDevices);
    }

    @GetMapping("/my-devices")
    @Operation(summary = "获取指定用户的所有设备")
    @Parameter(name = "userId", description = "用户ID", required = false, example = "4")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getMyDevices() {
        Long userId = getLoginUserId();
        if (userId == null) {
            org.slf4j.LoggerFactory.getLogger(getClass()).warn("获取当前用户信息失败 - 用户ID为null，可能是token验证失败");
            throw new ServiceException(USER_NOT_EXISTS);
        }
        // 优先使用参数中的userId，如果没有则使用当前登录用户的userId
        log.info("[IotAppDeviceController] 获取用户设备列表请求，参数用户ID: {}, 当前登录用户ID: {}, 最终使用用户ID: {}",
                userId, SecurityFrameworkUtils.getLoginUserId(), userId);

        
        try {
            // 查询当前用户在 iot_user_device 表中的所有设备
            String sql = "SELECT ud.id, ud.device_id, ud.custom_device_name, ud.MasterSlave, ud.room_id, " +
                        "ud.is_favorite, ud.sort_order, ud.status, ud.create_time, ud.deleted, " +
                        "d.device_name as original_device_name, d.device_type, d.state, d.product_id, " +
                        "d.product_key, d.online_time, d.offline_time " +
                        "FROM iot_user_device ud " +
                        "LEFT JOIN iot_device d ON ud.device_id = d.id " +
                        "WHERE ud.user_id = ? AND ud.deleted = 0 AND ud.status = 1 " +
                        "ORDER BY ud.sort_order ASC, ud.create_time DESC";
            
            List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, userId);
            
            // 按主副机分组
            List<Map<String, Object>> masterDevices = new ArrayList<>();
            List<Map<String, Object>> slaveDevices = new ArrayList<>();
            
            for (Map<String, Object> row : rows) {
                String masterSlave = (String) row.get("MasterSlave");
                Map<String, Object> deviceInfo = new HashMap<>();
                deviceInfo.put("id", row.get("id"));
                deviceInfo.put("deviceId", row.get("device_id"));
                deviceInfo.put("customDeviceName", row.get("custom_device_name"));
                deviceInfo.put("originalDeviceName", row.get("original_device_name"));
                deviceInfo.put("masterSlave", masterSlave);
                deviceInfo.put("roomId", row.get("room_id"));
                deviceInfo.put("isFavorite", row.get("is_favorite"));
                deviceInfo.put("sortOrder", row.get("sort_order"));
                deviceInfo.put("deviceType", row.get("device_type"));
                deviceInfo.put("state", row.get("state"));
                deviceInfo.put("productId", row.get("product_id"));
                deviceInfo.put("productKey", row.get("product_key"));
                deviceInfo.put("onlineTime", row.get("online_time"));
                deviceInfo.put("offlineTime", row.get("offline_time"));
                
                // 确保createTime是UTC时间格式
                Object createTimeObj = row.get("create_time");
                if (createTimeObj instanceof java.sql.Timestamp) {
                    java.sql.Timestamp timestamp = (java.sql.Timestamp) createTimeObj;
                    // 转换为UTC时间字符串
                    String utcTimeStr = timestamp.toInstant().toString();
                    deviceInfo.put("createTime", utcTimeStr);
                    log.debug("[getMyDevices] 设备 {} 的创建时间: {} (UTC)", row.get("device_id"), utcTimeStr);
                } else {
                    deviceInfo.put("createTime", createTimeObj);
                }
                
                if ("Master".equals(masterSlave)) {
                    masterDevices.add(deviceInfo);
                } else if ("Slave".equals(masterSlave)) {
                    slaveDevices.add(deviceInfo);
                }
            }
            
            Map<String, Object> result = Map.of(
                "masterDevices", masterDevices,
                "slaveDevices", slaveDevices,
                "totalCount", rows.size()
            );
            
            log.info("[IotAppDeviceController] 获取用户设备列表成功，用户ID: {}, 主机数量: {}, 副机数量: {}, 总计: {}", 
                userId, masterDevices.size(), slaveDevices.size(), rows.size());
            return success(List.of(result));
            
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取用户设备列表失败，用户ID: {}", userId, e);
            return CommonResult.error(500, "获取设备列表失败：" + e.getMessage());
        }
    }

    @PostMapping("/add-user-device")
    @Operation(summary = "添加用户设备")
    @TenantIgnore
    public CommonResult<Boolean> addUserDevice(@RequestBody Map<String, Object> params) {
        Long userId = getLoginUserId();
        if (userId == null) {
            org.slf4j.LoggerFactory.getLogger(getClass()).warn("获取当前用户信息失败 - 用户ID为null，可能是token验证失败");
            throw new ServiceException(USER_NOT_EXISTS);
        }
        log.info("[IotAppDeviceController] 添加用户设备请求，用户ID: {}, 参数: {}", userId, params);

        try {
            // 获取参数
            Long deviceId = Long.valueOf(params.get("deviceId").toString());
            String deviceName = (String) params.get("deviceName");
            String wifiSsid = (String) params.get("wifiSsid");
            String wifiPassword = (String) params.get("wifiPassword");

            // 检查是否已经添加过该设备
            String checkSql = "SELECT COUNT(*) FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
            Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId, deviceId);

            if (count != null && count > 0) {
                log.warn("[IotAppDeviceController] 设备已经添加过了，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(400, "设备已经添加过了");
            }

            // 获取当前北京时间
            java.time.ZonedDateTime beijingTime = java.time.ZonedDateTime.now(java.time.ZoneId.of("Asia/Shanghai"));
            java.time.LocalDateTime beijingDateTime = beijingTime.toLocalDateTime();
            
            log.info("[IotAppDeviceController] 当前北京时间: {}", beijingDateTime);

            // 插入用户设备关联记录，使用当前北京时间
            String insertSql = "INSERT INTO iot_user_device (user_id, device_id, device_name, wifi_ssid, wifi_password, status, create_time, update_time, creator, updater, deleted, tenant_id) " +
                              "VALUES (?, ?, ?, ?, ?, 1, ?, ?, '', '', 0, 1)";

            int result = jdbcTemplate.update(insertSql, userId, deviceId, deviceName, wifiSsid, wifiPassword, beijingDateTime, beijingDateTime);

            if (result > 0) {
                log.info("[IotAppDeviceController] 用户设备添加成功，用户ID: {}, 设备ID: {}, 设备名称: {}, WIFI: {}, 添加时间: {}", 
                    userId, deviceId, deviceName, wifiSsid, beijingDateTime);
                return success(true);
            } else {
                log.error("[IotAppDeviceController] 用户设备添加失败，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(500, "添加失败");
            }

        } catch (Exception e) {
            log.error("[IotAppDeviceController] 添加用户设备异常，用户ID: {}, 参数: {}", userId, params, e);
            return CommonResult.error(500, "添加失败：" + e.getMessage());
        }
    }

    @PostMapping("/save-user-device")
    @Operation(summary = "保存用户选择的设备到iot_user_device表")
    @TenantIgnore
    public CommonResult<Boolean> saveUserDevice(@RequestBody Map<String, Object> params) {
        Long userId = getLoginUserId();
        if (userId == null) {
            org.slf4j.LoggerFactory.getLogger(getClass()).warn("获取当前用户信息失败 - 用户ID为null，可能是token验证失败");
            throw new ServiceException(USER_NOT_EXISTS);
        }
        log.info("[IotAppDeviceController] 保存用户设备请求，用户ID: {}, 参数: {}", userId, params);

        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 获取参数
            Long deviceId = Long.valueOf(params.get("deviceId").toString());
            String customDeviceName = (String) params.get("customDeviceName");
            String masterSlave = (String) params.get("masterSlave"); // Master/Slave
            Long roomId = params.get("roomId") != null ? Long.valueOf(params.get("roomId").toString()) : null;
            Boolean isFavorite = params.get("isFavorite") != null ? Boolean.valueOf(params.get("isFavorite").toString()) : false;
            Integer sortOrder = params.get("sortOrder") != null ? Integer.valueOf(params.get("sortOrder").toString()) : 0;

            // 检查是否已经添加过该设备
            String checkSql = "SELECT COUNT(*) FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
            Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId, deviceId);

            if (count != null && count > 0) {
                log.warn("[IotAppDeviceController] 设备已经添加过了，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(400, "设备已经添加过了");
            }

            // 获取当前北京时间
            java.time.ZonedDateTime beijingTime = java.time.ZonedDateTime.now(java.time.ZoneId.of("Asia/Shanghai"));
            java.time.LocalDateTime beijingDateTime = beijingTime.toLocalDateTime();
            
            log.info("[IotAppDeviceController] 当前北京时间: {}", beijingDateTime);

            // 插入用户设备关联记录到iot_user_device表，使用当前北京时间
            String insertSql = "INSERT INTO iot_user_device (user_id, device_id, custom_device_name, MasterSlave, room_id, is_favorite, sort_order, status, creator, create_time, updater, update_time, deleted, tenant_id) " +
                              "VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, 0, ?)";

            int result = jdbcTemplate.update(insertSql, 
                userId, 
                deviceId, 
                customDeviceName, 
                masterSlave, 
                roomId, 
                isFavorite ? 1 : 0, 
                sortOrder, 
                userId.toString(), 
                beijingDateTime, // 使用当前北京时间作为创建时间
                userId.toString(), 
                beijingDateTime, // 使用当前北京时间作为更新时间
                1 // tenant_id
            );

            if (result > 0) {
                log.info("[IotAppDeviceController] 用户设备保存成功，用户ID: {}, 设备ID: {}, 自定义名称: {}, 主副机: {}, 保存时间: {}", 
                    userId, deviceId, customDeviceName, masterSlave, beijingDateTime);
                
                // 处理设备属性值（兼容旧版本）
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> deviceProperties = (List<Map<String, Object>>) params.get("deviceProperties");
                if (deviceProperties != null && !deviceProperties.isEmpty()) {
                    this.saveDeviceProperties(deviceId, deviceProperties);
                }
                
                // 新增：处理用户选择的服务
                @SuppressWarnings("unchecked")
                List<Object> selectedServices = (List<Object>) params.get("selectedServices");
                if (selectedServices != null && !selectedServices.isEmpty()) {
                    this.saveUserSelectedServices(userId, deviceId, selectedServices);
                }
                
                return success(true);
            } else {
                log.error("[IotAppDeviceController] 用户设备保存失败，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(500, "保存失败");
            }

        } catch (Exception e) {
            log.error("[IotAppDeviceController] 保存用户设备异常，用户ID: {}, 参数: {}", userId, params, e);
            return CommonResult.error(500, "保存失败：" + e.getMessage());
        }
    }

    /**
     * 保存设备属性值
     */
    private void saveDeviceProperties(Long deviceId, List<Map<String, Object>> deviceProperties) {
        try {
            for (Map<String, Object> property : deviceProperties) {
                String identifier = (String) property.get("identifier");
                String value = (String) property.get("value");
                
                if (identifier != null && value != null) {
                    // 更新设备属性值
                    String updateSql = "UPDATE iot_device_property SET value = ?, update_time = NOW() " +
                                      "WHERE device_id = ? AND identifier = ?";
                    
                    int updateResult = jdbcTemplate.update(updateSql, value, deviceId, identifier);
                    
                    if (updateResult > 0) {
                        log.info("[saveDeviceProperties] 设备属性更新成功，设备ID: {}, 属性: {}, 值: {}", 
                            deviceId, identifier, value);
                    } else {
                        log.warn("[saveDeviceProperties] 设备属性更新失败，设备ID: {}, 属性: {}", 
                            deviceId, identifier);
                    }
                }
            }
        } catch (Exception e) {
            log.error("[saveDeviceProperties] 保存设备属性异常，设备ID: {}", deviceId, e);
        }
    }

    @GetMapping("/wifi-list")
    @Operation(summary = "获取WIFI列表")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getWifiList() {
        log.info("[IotAppDeviceController] 获取WIFI列表请求");

        // 模拟WIFI列表数据
        List<Map<String, Object>> wifiList = List.of(
            Map.of("ssid", "MyHome_WiFi", "signal", -45, "security", "WPA2"),
            Map.of("ssid", "Office_Network", "signal", -60, "security", "WPA2"),
            Map.of("ssid", "Guest_WiFi", "signal", -70, "security", "Open"),
            Map.of("ssid", "Neighbor_WiFi", "signal", -80, "security", "WPA2")
        );

        log.info("[IotAppDeviceController] 获取WIFI列表成功，数量: {}", wifiList.size());
        return success(wifiList);
    }

    @PostMapping("/add-to-group")
    @Operation(summary = "添加设备到分组")
    @TenantIgnore
    public CommonResult<Boolean> addDeviceToGroup(@Valid @RequestBody IotAppDeviceControlReqVO reqVO) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 添加设备到分组请求，用户ID: {}, 设备ID: {}, 分组ID: {}", userId, reqVO.getDeviceId(), reqVO.getGroupId());
        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，操作失败");
            return success(false);
        }
        deviceService.addDeviceToGroup(reqVO.getDeviceId(), reqVO.getGroupId());
        log.info("[IotAppDeviceController] 添加设备到分组成功");
        return success(true);
    }

    @PostMapping("/control")
    @Operation(summary = "控制设备")
    @TenantIgnore
    public CommonResult<Boolean> controlDevice(@Valid @RequestBody IotAppDeviceControlReqVO reqVO) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 控制设备请求，用户ID: {}, 设备ID: {}, 指令: {}", userId, reqVO.getDeviceId(), reqVO.getCommand());
        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，操作失败");
            return success(false);
        }
        deviceService.controlDevice(reqVO.getDeviceId(), reqVO.getCommand());
        log.info("[IotAppDeviceController] 控制设备成功");
        return success(true);
    }

    @PostMapping("/control-direct")
    @Operation(summary = "直接控制设备（发送MQTT指令）")
    @TenantIgnore
    public CommonResult<Boolean> controlDeviceDirect(@Valid @RequestBody IotAppDeviceControlReqVO reqVO) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 直接控制设备请求，用户ID: {}, 设备ID: {}, 指令: {}", userId, reqVO.getDeviceId(), reqVO.getCommand());
        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，操作失败");
            return success(false);
        }
        
        try {
            // 构造控制请求VO
            cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceControlReqVO controlReqVO = 
                new cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceControlReqVO();
            controlReqVO.setDeviceId(reqVO.getDeviceId());
            controlReqVO.setCommandType("thing.property.set");
            controlReqVO.setCommandParams(reqVO.getCommand());
            
            // 使用deviceMessageService发送控制指令
            deviceMessageService.sendDeviceControlMessage(controlReqVO);
            log.info("[IotAppDeviceController] 直接控制设备成功");
            return success(true);
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 直接控制设备失败", e);
            return CommonResult.error(500, "控制设备失败：" + e.getMessage());
        }
    }

    @PostMapping("/set-threshold")
    @Operation(summary = "设置设备阈值", description = "设置设备阈值, 控制工作电路")
    @TenantIgnore
    public CommonResult<Boolean> setThreshold(@RequestBody Map<String, Object> params) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 设置设备阈值请求，用户ID: {}, 参数: {}", userId, params);

        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }
        
        try {
            Long deviceId = Long.valueOf(params.get("deviceId").toString());
            String thresholdType = params.get("thresholdType").toString();
            Double thresholdValue = Double.valueOf(params.get("thresholdValue").toString());
            
            // 构造阈值设置请求VO
            cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceThresholdReqVO thresholdReqVO = 
                new cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceThresholdReqVO();
            thresholdReqVO.setDeviceId(deviceId);
            thresholdReqVO.setThresholdType(thresholdType);
            thresholdReqVO.setThresholdValue(thresholdValue);
            
            // 使用deviceMessageService发送阈值设置指令
            deviceMessageService.sendDeviceThresholdMessage(thresholdReqVO);
            log.info("[IotAppDeviceController] 设置设备阈值成功");
            return success(true);
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 设置设备阈值失败", e);
            return CommonResult.error(500, "设置设备阈值失败：" + e.getMessage());
        }
    }

    @PostMapping("/set-radar-settings")
    @Operation(summary = "设置设备雷达参数", description = "设置设备雷达参数, 对雷达进行调试")
    @TenantIgnore
    public CommonResult<Boolean> setRadarSettings(@RequestBody Map<String, Object> params) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 设置设备雷达参数请求，用户ID: {}, 参数: {}", userId, params);

        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }
        
        try {
            Long deviceId = Long.valueOf(params.get("deviceId").toString());
            @SuppressWarnings("unchecked")
            Map<String, Object> radarSettings = (Map<String, Object>) params.get("radarSettings");
            
            if (radarSettings == null || radarSettings.isEmpty()) {
                log.warn("[IotAppDeviceController] 雷达设置参数为空");
                return CommonResult.error(400, "雷达设置参数不能为空");
            }
            
            // 构造雷达设置请求VO
            cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceRadarReqVO radarReqVO = 
                new cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceRadarReqVO();
            radarReqVO.setDeviceId(deviceId);
            radarReqVO.setRadarSettings(radarSettings);
            
            // 使用deviceMessageService发送雷达设置指令
            deviceMessageService.sendDeviceRadarMessage(radarReqVO);
            log.info("[IotAppDeviceController] 设置设备雷达参数成功");
            return success(true);
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 设置设备雷达参数失败", e);
            return CommonResult.error(500, "设置设备雷达参数失败：" + e.getMessage());
        }
    }

    @PostMapping("/save-threshold")
    @Operation(summary = "保存设备阈值")
    @TenantIgnore
    public CommonResult<Boolean> saveThreshold(@RequestBody Map<String, Object> params) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        log.info("[IotAppDeviceController] 保存设备阈值请求，用户ID: {}, 参数: {}", userId, params);

        if (userId == null) {
            log.warn("[IotAppDeviceController] 用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 获取参数
            Long deviceId = Long.valueOf(params.get("deviceId").toString());
            Double voltageThreshold = params.get("voltageThreshold") != null ? 
                Double.valueOf(params.get("voltageThreshold").toString()) : 0.0;

            // 更新用户设备的电压阈值
            String updateSql = "UPDATE iot_user_device SET voltage = ?, update_time = NOW() " +
                              "WHERE user_id = ? AND device_id = ? AND deleted = 0";

            int result = jdbcTemplate.update(updateSql, voltageThreshold, userId, deviceId);

            if (result > 0) {
                log.info("[IotAppDeviceController] 设备阈值保存成功，用户ID: {}, 设备ID: {}, 电压阈值: {}", 
                    userId, deviceId, voltageThreshold);
                return success(true);
            } else {
                log.warn("[IotAppDeviceController] 设备阈值保存失败，未找到匹配的记录，用户ID: {}, 设备ID: {}", 
                    userId, deviceId);
                return CommonResult.error(404, "设备不存在");
            }

        } catch (Exception e) {
            log.error("[IotAppDeviceController] 保存设备阈值异常，用户ID: {}, 参数: {}", userId, params, e);
            return CommonResult.error(500, "保存失败：" + e.getMessage());
        }
    }

    @GetMapping("/get-threshold")
    @Operation(summary = "获取设备阈值")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Map<String, Object>> getThreshold(@RequestParam("deviceId") Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 查询用户设备的电压阈值
            String sql = "SELECT voltage FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
            
            Double voltageThreshold = jdbcTemplate.queryForObject(sql, Double.class, userId, deviceId);
            
            // 如果阈值为null，设置为0
            if (voltageThreshold == null) {
                voltageThreshold = 0.0;
            }

            Map<String, Object> result = Map.of("voltageThreshold", voltageThreshold);
            
            log.info("[IotAppDeviceController] 获取设备阈值成功，用户ID: {}, 设备ID: {}, 电压阈值: {}", 
                userId, deviceId, voltageThreshold);
            return success(result);

        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取设备阈值失败，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "获取阈值失败：" + e.getMessage());
        }
    }

    @GetMapping("/product-list")
    @Operation(summary = "获取所有可用产品列表")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getProductList() {
        List<cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO> products = productService.getProductList();
        List<Map<String, Object>> result = new java.util.ArrayList<>();
        for (var p : products) {
            if (Boolean.TRUE.equals(p.getDeleted()) || (p.getStatus() != null && p.getStatus() != 1)) continue;
            Map<String, Object> productInfo = new HashMap<>();
            productInfo.put("id", p.getId());
            productInfo.put("name", p.getName() != null ? p.getName() : "");
            productInfo.put("productKey", p.getProductKey() != null ? p.getProductKey() : "");
            productInfo.put("description", p.getDescription() != null ? p.getDescription() : "");
            productInfo.put("icon", p.getIcon() != null ? p.getIcon() : "");
            productInfo.put("picUrl", p.getPicUrl() != null ? p.getPicUrl() : "");
            productInfo.put("status", p.getStatus());
            productInfo.put("deviceType", p.getDeviceType());
            result.add(productInfo);
        }
        return success(result);
    }

    @GetMapping("/list-by-product")
    @Operation(summary = "根据产品ID获取设备列表")
    @TenantIgnore
    public CommonResult<List<IotAppDeviceRespVO>> getDeviceListByProductId(@RequestParam Long productId) {
        List<IotDeviceDO> list = deviceService.getDeviceListByProductId(productId);
        return success(BeanUtils.toBean(list, IotAppDeviceRespVO.class));
    }

    @GetMapping("/latest-data")
    @Operation(summary = "获取设备最新传感器数据")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getLatestDeviceData() {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }
        
        try {
            // 获取用户的所有设备
            List<IotDeviceDO> userDevices = deviceService.getDeviceListByUserId(userId);
            List<Map<String, Object>> result = new ArrayList<>();
            
            for (IotDeviceDO device : userDevices) {
                // 设备基本数据（传感器数据已移除）
                Map<String, Object> deviceData = new HashMap<>();
                deviceData.put("id", device.getId());
                deviceData.put("deviceName", device.getDeviceName() != null ? device.getDeviceName() : "");
                deviceData.put("productId", device.getProductId());
                deviceData.put("state", device.getState());
                result.add(deviceData);
            }
            
            log.info("[IotAppDeviceController] 获取设备最新数据成功，设备数量: {}", result.size());
            return success(result);
            
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取设备最新数据失败", e);
            return CommonResult.error(500, "获取设备数据失败：" + e.getMessage());
        }
    }

    @GetMapping("/property/latest")
    @Operation(summary = "获取设备最新属性")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getLatestDeviceProperties(@RequestParam("deviceId") Long deviceId) {
        try {
            // 1.1 获取设备信息
            IotDeviceDO device = deviceService.getDevice(deviceId);
            Assert.notNull(device, "设备不存在");
            
            // 1.2 获取设备最新属性
            Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);
            
            // 1.3 根据 productId + type 查询属性类型的物模型
            List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductIdAndType(
                    device.getProductId(), IotThingModelTypeEnum.PROPERTY.getType());

            // 2. 基于 thingModels 遍历，拼接 properties
            List<Map<String, Object>> result = new ArrayList<>();
            for (IotThingModelDO thingModel : thingModels) {
                ThingModelProperty thingModelProperty = thingModel.getProperty();
                Assert.notNull(thingModelProperty, "属性不能为空");
                
                Map<String, Object> item = new HashMap<>();
                item.put("identifier", thingModel.getIdentifier());
                item.put("name", thingModel.getName());
                item.put("dataType", thingModelProperty.getDataType());
                item.put("dataSpecs", thingModelProperty.getDataSpecs());
                item.put("dataSpecsList", thingModelProperty.getDataSpecsList());
                
                IotDevicePropertyDO property = properties.get(thingModel.getIdentifier());
                if (property != null) {
                    item.put("value", property.getValue());
                    item.put("updateTime", LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
                } else {
                    item.put("value", null);
                    item.put("updateTime", null);
                }
                
                result.add(item);
            }
            
            log.info("[getLatestDeviceProperties][设备ID:{} 查询到{}个属性]", deviceId, result.size());
            return CommonResult.success(result);
        } catch (Exception e) {
            log.error("[getLatestDeviceProperties][设备ID:{} 查询属性失败]", deviceId, e);
            return CommonResult.error(500, "获取设备属性失败：" + e.getMessage());
        }
    }

    @GetMapping("/service/latest")
    @Operation(summary = "获取设备最新属性")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getLatestDeviceServices(@RequestParam("deviceId") Long deviceId) {
        try {
            // 1.1 获取设备信息
            IotDeviceDO device = deviceService.getDevice(deviceId);
            Assert.notNull(device, "设备不存在");

            // 1.2 获取设备最新属性
            Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);

            // 1.3 根据 productId + type 查询属性类型的物模型
            List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductIdAndType(
                    device.getProductId(), IotThingModelTypeEnum.SERVICE.getType());

            // 2. 基于 thingModels 遍历，拼接 properties
            List<Map<String, Object>> result = new ArrayList<>();
            for (IotThingModelDO thingModel : thingModels) {
                ThingModelService thingModelService = thingModel.getService();
                Assert.notNull(thingModelService, "属性不能为空");

                Map<String, Object> item = new HashMap<>();
                item.put("identifier", thingModel.getIdentifier());
                item.put("name", thingModel.getName());
                item.put("dataType",  thingModelService.getInputParams().stream().findFirst().orElse(new ThingModelParam()).getDataType());
                item.put("dataSpecs", thingModelService.getInputParams().stream().findFirst().orElse(new ThingModelParam()).getDataSpecs());
                item.put("inputParams", thingModelService.getInputParams());

                IotDevicePropertyDO property = properties.get(thingModel.getIdentifier());
                if (property != null) {
                    item.put("value", property.getValue());
                    item.put("updateTime", LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
                } else {
                    item.put("value", null);
                    item.put("updateTime", null);
                }

                result.add(item);
            }

            log.info("[getLatestDeviceProperties][设备ID:{} 查询到{}个属性]", deviceId, result.size());
            return CommonResult.success(result);
        } catch (Exception e) {
            log.error("[getLatestDeviceProperties][设备ID:{} 查询属性失败]", deviceId, e);
            return CommonResult.error(500, "获取设备属性失败：" + e.getMessage());
        }
    }

    /**
     * 从 iot_user_device 表中获取用户选择的设备
     * 使用真实的数据库查询
     */
    private List<IotAppDeviceRespVO> getUserDevicesFromUserDeviceTable(Long userId) {
        try {
            log.info("[IotAppDeviceController] 查询用户设备，用户ID: {}", userId);

            // 直接使用SQL查询用户设备
            String sql = "SELECT ud.device_id, ud.device_name as user_device_name, ud.deleted, " +
                        "d.id, d.device_name, d.device_type, d.state, d.create_time, " +
                        "d.product_id, d.product_key " +
                        "FROM iot_user_device ud " +
                        "LEFT JOIN iot_device d ON ud.device_id = d.id " +
                        "WHERE ud.user_id = ? AND ud.deleted = 0 AND ud.status = 1 " +
                        "ORDER BY ud.create_time DESC";

            List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, userId);

            List<IotAppDeviceRespVO> result = new ArrayList<>();
            for (Map<String, Object> row : rows) {
                IotAppDeviceRespVO respVO = new IotAppDeviceRespVO();
                respVO.setId(((Number) row.get("device_id")).longValue());
                respVO.setDeviceName((String) row.get("user_device_name")); // 使用用户自定义的设备名称
                respVO.setDeviceType(row.get("device_type") != null ? ((Number) row.get("device_type")).intValue() : 0);
                respVO.setState(row.get("state") != null ? ((Number) row.get("state")).intValue() : 0);
                respVO.setProductId(row.get("product_id") != null ? ((Number) row.get("product_id")).longValue() : null);
                respVO.setProductKey((String) row.get("product_key"));
                if (row.get("create_time") != null) {
                    respVO.setCreateTime((java.time.LocalDateTime) row.get("create_time"));
                }
                result.add(respVO);
            }

            log.info("[IotAppDeviceController] 查询用户设备成功，用户ID: {}, 设备数量: {}", userId, result.size());
            return result;

        } catch (Exception e) {
            log.error("[IotAppDeviceController] 查询用户设备失败，用户ID: {}", userId, e);
            return new ArrayList<>();
        }
    }

    @GetMapping("/energy/history")
    @Operation(summary = "获取设备能源数据历史记录")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1")
    @Parameter(name = "limit", description = "限制数量", required = false, example = "50")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getDeviceEnergyHistory(@RequestParam("deviceId") Long deviceId,
                                                                         @RequestParam(value = "limit", defaultValue = "50") int limit) {
        log.info("[IotAppDeviceController] 获取设备能源历史数据，设备ID: {}, 限制数量: {}", deviceId, limit);
        
        try {
            List<Map<String, Object>> energyHistory = deviceEnergyService.getDeviceEnergyHistory(deviceId, limit);
            log.info("[IotAppDeviceController] 获取设备能源历史数据成功，数据条数: {}", energyHistory.size());
            return success(energyHistory);
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取设备能源历史数据失败，设备ID: {}", deviceId, e);
            return success(new ArrayList<>());
        }
    }

    @GetMapping("/energy/latest")
    @Operation(summary = "获取设备最新能源数据")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1")
    @TenantIgnore
    public CommonResult<Map<String, Object>> getLatestDeviceEnergy(@RequestParam("deviceId") Long deviceId) {
        log.info("[IotAppDeviceController] 获取设备最新能源数据，设备ID: {}", deviceId);
        
        try {
            Map<String, Object> latestEnergy = deviceEnergyService.getLatestDeviceEnergy(deviceId);
            log.info("[IotAppDeviceController] 获取设备最新能源数据成功");
            return success(latestEnergy);
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取设备最新能源数据失败，设备ID: {}", deviceId, e);
            return success(null);
        }
    }

    @GetMapping("/user-device-detail")
    @Operation(summary = "获取用户设备详情")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Map<String, Object>> getUserDeviceDetail(@RequestParam("deviceId") Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        
        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }
        
        try {
            // 查询用户在 iot_user_device 表中的设备详情
            String sql = "SELECT ud.id, ud.device_id, ud.custom_device_name, ud.MasterSlave, ud.room_id, " +
                        "ud.is_favorite, ud.sort_order, ud.status, ud.create_time, ud.deleted, " +
                        "d.device_name as original_device_name, d.device_type, d.state, d.product_id, " +
                        "d.product_key, d.online_time, d.offline_time " +
                        "FROM iot_user_device ud " +
                        "LEFT JOIN iot_device d ON ud.device_id = d.id " +
                        "WHERE ud.user_id = ? AND ud.device_id = ? AND ud.deleted = 0 AND ud.status = 1";
            
            List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql, userId, deviceId);
            
            if (rows.isEmpty()) {
                log.warn("[IotAppDeviceController] 未找到用户设备，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(404, "设备不存在");
            }
            
            Map<String, Object> row = rows.get(0);
            Map<String, Object> deviceInfo = new HashMap<>();
            
            deviceInfo.put("id", row.get("id"));
            deviceInfo.put("deviceId", row.get("device_id"));
            deviceInfo.put("customDeviceName", row.get("custom_device_name"));
            deviceInfo.put("originalDeviceName", row.get("original_device_name"));
            deviceInfo.put("masterSlave", row.get("MasterSlave"));
            deviceInfo.put("roomId", row.get("room_id"));
            deviceInfo.put("isFavorite", row.get("is_favorite"));
            deviceInfo.put("sortOrder", row.get("sort_order"));
            deviceInfo.put("deviceType", row.get("device_type"));
            deviceInfo.put("state", row.get("state"));
            deviceInfo.put("productId", row.get("product_id"));
            deviceInfo.put("productKey", row.get("product_key"));
            deviceInfo.put("onlineTime", row.get("online_time"));
            deviceInfo.put("offlineTime", row.get("offline_time"));
            
            // 确保createTime是UTC时间格式
            Object createTimeObj = row.get("create_time");
            if (createTimeObj instanceof java.sql.Timestamp) {
                java.sql.Timestamp timestamp = (java.sql.Timestamp) createTimeObj;
                // 转换为UTC时间字符串
                String utcTimeStr = timestamp.toInstant().toString();
                deviceInfo.put("createTime", utcTimeStr);
                log.info("[getUserDeviceDetail] 设备 {} 的用户添加时间: {} (UTC)", deviceId, utcTimeStr);
            } else {
                deviceInfo.put("createTime", createTimeObj);
            }
            
            log.info("[IotAppDeviceController] 获取用户设备详情成功，用户ID: {}, 设备ID: {}", userId, deviceId);
            return success(deviceInfo);
            
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取用户设备详情失败，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "获取设备详情失败：" + e.getMessage());
        }
    }

    @GetMapping("/device-product-info")
    @Operation(summary = "根据设备ID获取产品信息")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Map<String, Object>> getDeviceProductInfo(@RequestParam("deviceId") Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 1. 根据设备ID查询iot_device表获取product_key
            String deviceSql = "SELECT product_key FROM iot_device WHERE id = ? AND deleted = 0";
            String productKey = jdbcTemplate.queryForObject(deviceSql, String.class, deviceId);
            
            if (productKey == null) {
                log.warn("[IotAppDeviceController] 设备不存在，设备ID: {}", deviceId);
                return CommonResult.error(404, "设备不存在");
            }
            
            log.info("[IotAppDeviceController] 找到设备，设备ID: {}, productKey: {}", deviceId, productKey);

            // 2. 根据product_key查询iot_product表获取产品信息
            String productSql = "SELECT id, name, description, device_type, status, icon, create_time, update_time " +
                               "FROM iot_product WHERE product_key = ? AND deleted = 0";
            
            Map<String, Object> productInfo = jdbcTemplate.queryForMap(productSql, productKey);
            
            if (productInfo == null) {
                log.warn("[IotAppDeviceController] 产品不存在，productKey: {}", productKey);
                return CommonResult.error(404, "产品不存在");
            }
            
            log.info("[IotAppDeviceController] 找到产品信息，productKey: {}, 产品名称: {}", 
                productKey, productInfo.get("name"));

            // 3. 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("deviceId", deviceId);
            result.put("productKey", productKey);
            result.put("productId", productInfo.get("id"));
            result.put("productName", productInfo.get("name"));
            result.put("productDescription", productInfo.get("description"));
            result.put("deviceType", productInfo.get("device_type"));
            result.put("productStatus", productInfo.get("status"));
            result.put("productIcon", productInfo.get("icon"));
            result.put("productCreateTime", productInfo.get("create_time"));
            result.put("productUpdateTime", productInfo.get("update_time"));

            return success(result);
            
        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取设备产品信息失败，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "获取产品信息失败：" + e.getMessage());
        }
    }

    @GetMapping("/get-radar-settings")
    @Operation(summary = "获取设备雷达属性设置")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Map<String, Object>> getRadarSettings(@RequestParam("deviceId") Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 检查设备是否属于当前用户
            String checkSql = "SELECT COUNT(*) FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
            Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId, deviceId);

            if (count == null || count == 0) {
                log.warn("[IotAppDeviceController] 设备不存在或不属于当前用户，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(404, "设备不存在或不属于当前用户");
            }

            // 从iot_user_device表的radar字段获取雷达设置
            String radarSql = "SELECT radar FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
            String radarJson = jdbcTemplate.queryForObject(radarSql, String.class, userId, deviceId);

            // 构建返回结果
            Map<String, Object> result = new HashMap<>();

            // 如果数据库中有雷达设置，则解析JSON并返回结果
            if (radarJson != null && !radarJson.trim().isEmpty()) {
                try {
                    Map<String, Object> radarSettings = JsonUtils.parseObject(radarJson, Map.class);
                    
                    // 直接使用数据库中的值
                    result.put("maximum_distance", radarSettings.get("maximum_distance"));
                    result.put("motion_trigger_threshold", radarSettings.get("motion_trigger_threshold"));
                    result.put("micro_motion_threshold", radarSettings.get("micro_motion_threshold"));
                    result.put("power_interference_alarm", radarSettings.get("power_interference_alarm"));
                    result.put("target_loss_latency", radarSettings.get("target_loss_latency"));
                    
                    log.info("[IotAppDeviceController] 解析雷达设置JSON成功: {}", radarJson);
                } catch (Exception e) {
                    log.warn("[IotAppDeviceController] 解析雷达设置JSON失败: {}, 返回空值", radarJson, e);
                    // JSON解析失败时返回空值
                    result.put("maximum_distance", null);
                    result.put("motion_trigger_threshold", null);
                    result.put("micro_motion_threshold", null);
                    result.put("power_interference_alarm", 0);
                    result.put("target_loss_latency", null);
                }
            } else {
                log.info("[IotAppDeviceController] 数据库中无雷达设置，返回空值");
                // 数据库中没有雷达设置时返回空值
                result.put("maximum_distance", null);
                result.put("motion_trigger_threshold", null);
                result.put("micro_motion_threshold", null);
                result.put("power_interference_alarm", 0);
                result.put("target_loss_latency", null);
            }

            log.info("[IotAppDeviceController] 获取设备雷达属性设置成功，用户ID: {}, 设备ID: {}, 设置: {}", userId, deviceId, result);
            return success(result);

        } catch (Exception e) {
            log.error("[IotAppDeviceController] 获取设备雷达属性设置失败，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "获取雷达属性设置失败：" + e.getMessage());
        }
    }

    // @PostMapping("/radat-control")
    // @Operation(summary = "下发设备控制指令")
    // public CommonResult<Boolean> controlDevice(@Valid @RequestBody IotDeviceControlReqVO reqVO) {
    //     deviceMessageService.sendDeviceControlMessage(reqVO);
    //     return success(true);
    // }

   @PostMapping("/save-radar-settings")
   @Operation(summary = "保存设备雷达属性设置")
   @TenantIgnore
   public CommonResult<Boolean> saveRadarSettings(@RequestBody Map<String, Object> params) {
       Long userId = SecurityFrameworkUtils.getLoginUserId();

       if (userId == null) {
           log.warn("用户未登录，操作失败");
           return CommonResult.error(401, "用户未登录");
       }

       try {
           Long deviceId = Long.valueOf(params.get("deviceId").toString());

           // 检查设备是否属于当前用户
           String checkSql = "SELECT COUNT(*) FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
           Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId, deviceId);

           if (count == null || count == 0) {
               log.warn("[IotAppDeviceController] 设备不存在或不属于当前用户，用户ID: {}, 设备ID: {}", userId, deviceId);
               return CommonResult.error(404, "设备不存在或不属于当前用户");
           }

           // 从params中获取radarSettings对象
           @SuppressWarnings("unchecked")
           Map<String, Object> radarSettings = (Map<String, Object>) params.get("radarSettings");

           if (radarSettings == null || radarSettings.isEmpty()) {
               log.warn("[IotAppDeviceController] 雷达设置参数为空");
               return CommonResult.error(400, "雷达设置参数不能为空");
           }

           log.info("[IotAppDeviceController] 原始雷达设置参数: {}", radarSettings);
           log.info("[IotAppDeviceController] 最大距离原始值: {} (类型: {})", radarSettings.get("maximum_distance"),
               radarSettings.get("maximum_distance") != null ? radarSettings.get("maximum_distance").getClass().getSimpleName() : "null");
           log.info("[IotAppDeviceController] 运动触发门限原始值: {} (类型: {})", radarSettings.get("motion_trigger_threshold"),
               radarSettings.get("motion_trigger_threshold") != null ? radarSettings.get("motion_trigger_threshold").getClass().getSimpleName() : "null");
           log.info("[IotAppDeviceController] 微动门限原始值: {} (类型: {})", radarSettings.get("micro_motion_threshold"),
               radarSettings.get("micro_motion_threshold") != null ? radarSettings.get("micro_motion_threshold").getClass().getSimpleName() : "null");
           log.info("[IotAppDeviceController] 电源干扰报警原始值: {} (类型: {})", radarSettings.get("power_interference_alarm"),
               radarSettings.get("power_interference_alarm") != null ? radarSettings.get("power_interference_alarm").getClass().getSimpleName() : "null");
           log.info("[IotAppDeviceController] 目标消失延迟原始值: {} (类型: {})", radarSettings.get("target_loss_latency"),
               radarSettings.get("target_loss_latency") != null ? radarSettings.get("target_loss_latency").getClass().getSimpleName() : "null");

           // 构建雷达设置JSON数据，处理字符串到数值的转换
           Map<String, Object> processedRadarSettings = new HashMap<>();

           // 处理最大距离
           Object maxDistance = radarSettings.get("maximum_distance");
           log.info("[IotAppDeviceController] 处理最大距离 - 原始值: {} (类型: {})", maxDistance,
               maxDistance != null ? maxDistance.getClass().getSimpleName() : "null");
           if (maxDistance != null && !maxDistance.toString().trim().isEmpty()) {
               try {
                   Double convertedValue = Double.valueOf(maxDistance.toString());
                   processedRadarSettings.put("maximum_distance", convertedValue);
                   log.info("[IotAppDeviceController] 最大距离转换成功: {} -> {}", maxDistance, convertedValue);
               } catch (NumberFormatException e) {
                   log.warn("[IotAppDeviceController] 最大距离参数格式错误: {}", maxDistance);
                   processedRadarSettings.put("maximum_distance", null);
               }
           } else {
               processedRadarSettings.put("maximum_distance", null);
               log.info("[IotAppDeviceController] 最大距离为空，设置为null");
           }

           // 处理运动触发门限
           Object motionThreshold = radarSettings.get("motion_trigger_threshold");
           log.info("[IotAppDeviceController] 处理运动触发门限 - 原始值: {} (类型: {})", motionThreshold,
               motionThreshold != null ? motionThreshold.getClass().getSimpleName() : "null");
           if (motionThreshold != null && !motionThreshold.toString().trim().isEmpty()) {
               try {
                   Integer convertedValue = Integer.valueOf(motionThreshold.toString());
                   processedRadarSettings.put("motion_trigger_threshold", convertedValue);
                   log.info("[IotAppDeviceController] 运动触发门限转换成功: {} -> {}", motionThreshold, convertedValue);
               } catch (NumberFormatException e) {
                   log.warn("[IotAppDeviceController] 运动触发门限参数格式错误: {}", motionThreshold);
                   processedRadarSettings.put("motion_trigger_threshold", null);
               }
           } else {
               processedRadarSettings.put("motion_trigger_threshold", null);
               log.info("[IotAppDeviceController] 运动触发门限为空，设置为null");
           }

           // 处理微动门限
           Object microMotionThreshold = radarSettings.get("micro_motion_threshold");
           log.info("[IotAppDeviceController] 处理微动门限 - 原始值: {} (类型: {})", microMotionThreshold,
               microMotionThreshold != null ? microMotionThreshold.getClass().getSimpleName() : "null");
           if (microMotionThreshold != null && !microMotionThreshold.toString().trim().isEmpty()) {
               try {
                   Integer convertedValue = Integer.valueOf(microMotionThreshold.toString());
                   processedRadarSettings.put("micro_motion_threshold", convertedValue);
                   log.info("[IotAppDeviceController] 微动门限转换成功: {} -> {}", microMotionThreshold, convertedValue);
               } catch (NumberFormatException e) {
                   log.warn("[IotAppDeviceController] 微动门限参数格式错误: {}", microMotionThreshold);
                   processedRadarSettings.put("micro_motion_threshold", null);
               }
           } else {
               processedRadarSettings.put("micro_motion_threshold", null);
               log.info("[IotAppDeviceController] 微动门限为空，设置为null");
           }

           // 处理电源干扰报警（只读，保持原值）
           Object powerInterference = radarSettings.get("power_interference_alarm");
           log.info("[IotAppDeviceController] 处理电源干扰报警 - 原始值: {} (类型: {})", powerInterference,
               powerInterference != null ? powerInterference.getClass().getSimpleName() : "null");
           if (powerInterference != null) {
               try {
                   Integer convertedValue = Integer.valueOf(powerInterference.toString());
                   processedRadarSettings.put("power_interference_alarm", convertedValue);
                   log.info("[IotAppDeviceController] 电源干扰报警转换成功: {} -> {}", powerInterference, convertedValue);
               } catch (NumberFormatException e) {
                   log.warn("[IotAppDeviceController] 电源干扰报警参数格式错误: {}", powerInterference);
                   processedRadarSettings.put("power_interference_alarm", 0);
               }
           } else {
               processedRadarSettings.put("power_interference_alarm", 0);
               log.info("[IotAppDeviceController] 电源干扰报警为空，设置为0");
           }

           // 处理目标消失延迟
           Object targetLossLatency = radarSettings.get("target_loss_latency");
           log.info("[IotAppDeviceController] 处理目标消失延迟 - 原始值: {} (类型: {})", targetLossLatency,
               targetLossLatency != null ? targetLossLatency.getClass().getSimpleName() : "null");
           if (targetLossLatency != null && !targetLossLatency.toString().trim().isEmpty()) {
               try {
                   Integer convertedValue = Integer.valueOf(targetLossLatency.toString());
                   processedRadarSettings.put("target_loss_latency", convertedValue);
                   log.info("[IotAppDeviceController] 目标消失延迟转换成功: {} -> {}", targetLossLatency, convertedValue);
               } catch (NumberFormatException e) {
                   log.warn("[IotAppDeviceController] 目标消失延迟参数格式错误: {}", targetLossLatency);
                   processedRadarSettings.put("target_loss_latency", null);
               }
           } else {
               processedRadarSettings.put("target_loss_latency", null);
               log.info("[IotAppDeviceController] 目标消失延迟为空，设置为null");
           }

           String radarJson = JsonUtils.toJsonString(processedRadarSettings);
           log.info("[IotAppDeviceController] 处理后的雷达设置JSON: {}", radarJson);

           // 保存雷达设置到iot_user_device表的radar字段
           String updateSql = "UPDATE iot_user_device SET radar = ?, update_time = NOW() WHERE user_id = ? AND device_id = ? AND deleted = 0";
           int result = jdbcTemplate.update(updateSql, radarJson, userId, deviceId);

           if (result > 0) {
               log.info("[IotAppDeviceController] 保存设备雷达属性设置成功，用户ID: {}, 设备ID: {}", userId, deviceId);
               
               // 发送设备控制指令
               try {
                   IotDeviceControlReqVO controlReqVO = new IotDeviceControlReqVO();
                   controlReqVO.setDeviceId(deviceId);
                   controlReqVO.setCommandType("thing.property.set");
                   controlReqVO.setCommandParams(radarJson);
                   
                   deviceMessageService.sendDeviceControlMessage(controlReqVO);
                   log.info("[IotAppDeviceController] 雷达设置设备控制指令发送成功，设备ID: {}, 参数: {}", deviceId, radarJson);
               } catch (Exception e) {
                   log.warn("[IotAppDeviceController] 雷达设置设备控制指令发送失败，设备ID: {}, 错误: {}", deviceId, e.getMessage());
                   // 不返回错误，因为数据库保存已经成功
               }
               
               return success(true);
           } else {
               log.error("[IotAppDeviceController] 保存设备雷达属性设置失败，用户ID: {}, 设备ID: {}", userId, deviceId);
               return CommonResult.error(500, "保存失败");
           }

       } catch (Exception e) {
           log.error("[IotAppDeviceController] 保存设备雷达属性设置失败，用户ID: {}, 参数: {}", userId, params, e);
           return CommonResult.error(500, "保存雷达属性设置失败：" + e.getMessage());
       }
   }

    @PostMapping("/delete-device")
    @Operation(summary = "删除用户设备", description = "删除用户设备")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Boolean> deleteDevice(@RequestParam("deviceId") Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 检查设备是否属于当前用户
            String checkSql = "SELECT COUNT(*) FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
            Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class, userId, deviceId);

            if (count == null || count == 0) {
                log.warn("[deleteDevice] 设备不存在或不属于当前用户，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(404, "设备不存在或不属于当前用户");
            }

            // 1. 清理设备相关的服务数据（包括数据库记录和Redis缓存）
            cleanupDeviceServices(userId, deviceId);

            // 2. 软删除用户设备（设置deleted=1）
            String deleteDeviceSql = "UPDATE iot_user_device SET deleted = 1, update_time = NOW() WHERE user_id = ? AND device_id = ? AND deleted = 0";
            int deviceResult = jdbcTemplate.update(deleteDeviceSql, userId, deviceId);

            if (deviceResult > 0) {
                log.info("[deleteDevice] 用户设备删除成功，用户ID: {}, 设备ID: {}", userId, deviceId);
                return success(true);
            } else {
                log.error("[deleteDevice] 用户设备删除失败，用户ID: {}, 设备ID: {}", userId, deviceId);
                return CommonResult.error(500, "删除失败");
            }

        } catch (Exception e) {
            log.error("[deleteDevice] 删除用户设备异常，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "删除失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存用户选择的服务到Redis和数据库
     */
    private void saveUserSelectedServices(Long userId, Long deviceId, List<Object> selectedServices) {
        try {
            log.info("[saveUserSelectedServices] 开始保存用户选择的服务，用户ID: {}, 设备ID: {}, 服务: {}", 
                userId, deviceId, selectedServices);
            
            // 1. 保存到Redis缓存（用于快速查询）
            // 提取服务标识符用于Redis缓存
            List<String> serviceIdentifiers = new ArrayList<>();
            for (Object service : selectedServices) {
                if (service instanceof Map) {
                    Map<String, Object> serviceMap = (Map<String, Object>) service;
                    String identifier = (String) serviceMap.get("identifier");
                    if (identifier != null) {
                        serviceIdentifiers.add(identifier);
                    }
                } else if (service instanceof String) {
                    // 兼容旧版本，如果传递的是字符串列表
                    serviceIdentifiers.add((String) service);
                }
            }
            
            String redisKey = String.format("iot:user:device:services:%d:%d", userId, deviceId);
            redisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(serviceIdentifiers), 24, TimeUnit.HOURS);
            log.info("[saveUserSelectedServices] Redis缓存保存成功，key: {}, 服务: {}", redisKey, serviceIdentifiers);
            
            // 2. 保存到数据库（持久化存储）
            // 先删除旧的服务记录
            String deleteSql = "DELETE FROM iot_user_device_services WHERE user_id = ? AND device_id = ?";
            jdbcTemplate.update(deleteSql, userId, deviceId);
            
            // 插入新的服务记录，包含service_name和description字段
            String insertSql = "INSERT INTO iot_user_device_services (user_id, device_id, service_identifier, service_name, description, create_time, update_time, deleted, tenant_id) VALUES (?, ?, ?, ?, ?, NOW(), NOW(), 0, ?)";
            
            for (Object service : selectedServices) {
                String serviceIdentifier;
                String serviceName;
                String description;
                
                if (service instanceof Map) {
                    // 新版本：从Map中获取完整信息
                    Map<String, Object> serviceMap = (Map<String, Object>) service;
                    serviceIdentifier = (String) serviceMap.get("identifier");
                    serviceName = (String) serviceMap.get("name");
                    description = (String) serviceMap.get("description");
                    
                    // 如果前端没有传递name或description，则使用默认值
                    if (serviceName == null || serviceName.trim().isEmpty()) {
                        serviceName = getServiceDisplayName(serviceIdentifier);
                    }
                    if (description == null || description.trim().isEmpty()) {
                        description = getServiceDescription(serviceIdentifier);
                    }
                } else if (service instanceof String) {
                    // 兼容旧版本：如果传递的是字符串，则使用默认值
                    serviceIdentifier = (String) service;
                    serviceName = getServiceDisplayName(serviceIdentifier);
                    description = getServiceDescription(serviceIdentifier);
                } else {
                    log.warn("[saveUserSelectedServices] 未知的服务数据类型: {}", service.getClass().getName());
                    continue;
                }
                
                jdbcTemplate.update(insertSql, userId, deviceId, serviceIdentifier, serviceName, description, 1);
                log.info("[saveUserSelectedServices] 数据库服务记录保存成功，用户ID: {}, 设备ID: {}, 服务: {}, 名称: {}, 描述: {}", 
                    userId, deviceId, serviceIdentifier, serviceName, description);
            }
            
            log.info("[saveUserSelectedServices] 用户选择的服务保存完成，用户ID: {}, 设备ID: {}, 服务数量: {}", 
                userId, deviceId, selectedServices.size());
                
        } catch (Exception e) {
            log.error("[saveUserSelectedServices] 保存用户选择的服务失败，用户ID: {}, 设备ID: {}, 服务: {}", 
                userId, deviceId, selectedServices, e);
            // 不抛出异常，避免影响主流程
        }
    }
    
    /**
     * 获取服务显示名称
     */
    private String getServiceDisplayName(String serviceIdentifier) {
        switch (serviceIdentifier) {
            case "control":
                return "控制服务";
            case "control1":
                return "控制1服务";
            default:
                return serviceIdentifier;
        }
    }
    
    /**
     * 获取服务描述
     */
    private String getServiceDescription(String serviceIdentifier) {
        switch (serviceIdentifier) {
            case "control":
                return "设备控制服务，用于开关控制";
            case "control1":
                return "设备控制1服务，用于其他控制功能";
            default:
                return "设备服务";
        }
    }
    
    @GetMapping("/user-device-services")
    @Operation(summary = "获取用户设备选择的服务")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getUserDeviceServices(@RequestParam("deviceId") Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 1. 强制清除Redis缓存，确保获取最新数据
            String redisKey = String.format("iot:user:device:services:%d:%d", userId, deviceId);
            redisTemplate.delete(redisKey);
            log.info("[getUserDeviceServices] 强制清除Redis缓存，用户ID: {}, 设备ID: {}", userId, deviceId);
            
            // 2. 从数据库获取完整信息（包含主键id和service_value）
            String sql = "SELECT id, service_identifier, service_name, description, service_value FROM iot_user_device_services WHERE user_id = ? AND device_id = ? AND deleted = 0 ORDER BY create_time";
            List<Map<String, Object>> services = jdbcTemplate.queryForList(sql, userId, deviceId);
            
            log.info("[getUserDeviceServices] 数据库查询结果，用户ID: {}, 设备ID: {}, SQL: {}, 结果: {}", 
                userId, deviceId, sql, services);
            
            // 调试：检查每个服务的字段
            for (int i = 0; i < services.size(); i++) {
                Map<String, Object> service = services.get(i);
                log.info("[getUserDeviceServices] 服务[{}] 字段详情: id={}, service_identifier={}, service_name={}, description={}, service_value={}", 
                    i, service.get("id"), service.get("service_identifier"), service.get("service_name"), 
                    service.get("description"), service.get("service_value"));
            }
            
            // 3. 如果没有service_name，则生成默认值
            for (Map<String, Object> service : services) {
                if (service.get("service_name") == null || ((String) service.get("service_name")).trim().isEmpty()) {
                    String identifier = (String) service.get("service_identifier");
                    service.put("service_name", getServiceDisplayName(identifier));
                }
                if (service.get("description") == null || ((String) service.get("description")).trim().isEmpty()) {
                    String identifier = (String) service.get("service_identifier");
                    service.put("description", getServiceDescription(identifier));
                }
            }
            
            // 4. 更新Redis缓存（缓存完整的服务信息，包含id字段）
            if (!services.isEmpty()) {
                redisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(services), 24, TimeUnit.HOURS);
                log.info("[getUserDeviceServices] Redis缓存更新成功，用户ID: {}, 设备ID: {}, 服务数量: {}, 缓存内容: {}", 
                    userId, deviceId, services.size(), JsonUtils.toJsonString(services));
            }
            
            log.info("[getUserDeviceServices] 获取用户设备服务成功，用户ID: {}, 设备ID: {}, 服务数量: {}", 
                userId, deviceId, services.size());
            return success(services);
            
        } catch (Exception e) {
            log.error("[getUserDeviceServices] 获取用户设备服务异常，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "获取服务失败：" + e.getMessage());
        }
    }
    

    
    @PostMapping("/delete-user-device-services")
    @Operation(summary = "删除用户设备选择的服务", description = "删除用户设备选择的服务")
    @Parameter(name = "deviceId", description = "设备ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Boolean> deleteUserDeviceServices(@RequestParam("deviceId") Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 1. 删除Redis缓存
            String redisKey = String.format("iot:user:device:services:%d:%d", userId, deviceId);
            redisTemplate.delete(redisKey);
            log.info("[deleteUserDeviceServices] Redis缓存删除成功，key: {}", redisKey);
            
            // 2. 软删除数据库记录
            String deleteSql = "UPDATE iot_user_device_services SET deleted = 1, update_time = NOW() WHERE user_id = ? AND device_id = ? AND deleted = 0";
            int result = jdbcTemplate.update(deleteSql, userId, deviceId);
            
            log.info("[deleteUserDeviceServices] 用户设备服务删除成功，用户ID: {}, 设备ID: {}, 影响记录数: {}", 
                userId, deviceId, result);
            return success(true);
            
        } catch (Exception e) {
            log.error("[deleteUserDeviceServices] 删除用户设备服务异常，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "删除服务失败：" + e.getMessage());
        }
    }
    
    @PostMapping("/update-service-value")
    @Operation(summary = "根据主键ID更新服务值", description = "更新服务值")
    @Parameter(name = "id", description = "服务记录主键ID", required = true, example = "1024")
    @Parameter(name = "serviceValue", description = "服务值", required = true, example = "1")
    @TenantIgnore
    public CommonResult<Boolean> updateServiceValue(@RequestParam("id") Long id, @RequestParam("serviceValue") String serviceValue) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 1. 验证服务记录是否存在且属于当前用户
            String checkSql = "SELECT user_id, device_id, service_identifier FROM iot_user_device_services WHERE id = ? AND deleted = 0";
            List<Map<String, Object>> records = jdbcTemplate.queryForList(checkSql, id);
            
            if (records.isEmpty()) {
                log.warn("[updateServiceValue] 服务记录不存在，ID: {}", id);
                return CommonResult.error(404, "服务记录不存在");
            }
            
            Map<String, Object> record = records.get(0);
            Long recordUserId = ((Number) record.get("user_id")).longValue();
            
            if (!recordUserId.equals(userId)) {
                log.warn("[updateServiceValue] 用户无权限操作此服务记录，用户ID: {}, 记录用户ID: {}, 服务ID: {}", userId, recordUserId, id);
                return CommonResult.error(403, "无权限操作此服务记录");
            }
            
            // 2. 更新服务值
            String updateSql = "UPDATE iot_user_device_services SET service_value = ?, update_time = NOW() WHERE id = ? AND deleted = 0";
            int result = jdbcTemplate.update(updateSql, serviceValue, id);
            
            if (result > 0) {
                // 3. 清理相关Redis缓存
                Long deviceId = ((Number) record.get("device_id")).longValue();
                String redisKey = String.format("iot:user:device:services:%d:%d", userId, deviceId);
                redisTemplate.delete(redisKey);
                log.info("[updateServiceValue] Redis缓存清理成功，key: {}", redisKey);
                
                log.info("[updateServiceValue] 服务值更新成功，用户ID: {}, 服务ID: {}, 服务值: {}", userId, id, serviceValue);
                return success(true);
            } else {
                log.warn("[updateServiceValue] 服务值更新失败，用户ID: {}, 服务ID: {}, 服务值: {}", userId, id, serviceValue);
                return CommonResult.error(500, "服务值更新失败");
            }
            
        } catch (Exception e) {
            log.error("[updateServiceValue] 更新服务值异常，用户ID: {}, 服务ID: {}, 服务值: {}", userId, id, serviceValue, e);
            return CommonResult.error(500, "更新服务值失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/get-service-value")
    @Operation(summary = "根据主键ID查询服务值")
    @Parameter(name = "id", description = "服务记录主键ID", required = true, example = "1024")
    @TenantIgnore
    public CommonResult<Map<String, Object>> getServiceValue(@RequestParam("id") Long id) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }

        try {
            // 查询服务记录信息
            String sql = "SELECT id, user_id, device_id, service_identifier, service_name, description, service_value FROM iot_user_device_services WHERE id = ? AND deleted = 0";
            List<Map<String, Object>> records = jdbcTemplate.queryForList(sql, id);
            
            if (records.isEmpty()) {
                log.warn("[getServiceValue] 服务记录不存在，ID: {}", id);
                return CommonResult.error(404, "服务记录不存在");
            }
            
            Map<String, Object> record = records.get(0);
            Long recordUserId = ((Number) record.get("user_id")).longValue();
            
            if (!recordUserId.equals(userId)) {
                log.warn("[getServiceValue] 用户无权限查询此服务记录，用户ID: {}, 记录用户ID: {}, 服务ID: {}", userId, recordUserId, id);
                return CommonResult.error(403, "无权限查询此服务记录");
            }
            
            log.info("[getServiceValue] 查询服务值成功，用户ID: {}, 服务ID: {}, 服务值: {}", userId, id, record.get("service_value"));
            return success(record);
            
        } catch (Exception e) {
            log.error("[getServiceValue] 查询服务值异常，用户ID: {}, 服务ID: {}", userId, id, e);
            return CommonResult.error(500, "查询服务值失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/admin/user-device-services")
    @Operation(summary = "管理员获取用户设备选择的服务")
    @Parameter(name = "userId", description = "用户ID", required = true, example = "1024")
    @Parameter(name = "deviceId", description = "设备ID", required = false, example = "1024")
    @TenantIgnore
    public CommonResult<List<Map<String, Object>>> getAdminUserDeviceServices(@RequestParam(value = "deviceId", required = false) Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }
        try {
            List<Map<String, Object>> services = new ArrayList<>();
            
            if (deviceId != null) {
                // 获取指定设备的服务
                String redisKey = String.format("iot:user:device:services:%d:%d", userId, deviceId);
                String cachedServices = redisTemplate.opsForValue().get(redisKey);
                
                if (cachedServices != null) {
                    try {
                        // 尝试解析为完整的服务信息
                        @SuppressWarnings("unchecked")
                        List<Object> rawServices = JsonUtils.parseArray(cachedServices, Object.class);
                        List<Map<String, Object>> cachedServicesList = new ArrayList<>();
                        
                        // 手动转换类型
                        for (Object rawService : rawServices) {
                            if (rawService instanceof Map) {
                                @SuppressWarnings("unchecked")
                                Map<String, Object> service = (Map<String, Object>) rawService;
                                cachedServicesList.add(service);
                            }
                        }
                        
                        // 检查是否包含service_name字段，如果没有则说明是旧格式缓存
                        if (!cachedServicesList.isEmpty() && cachedServicesList.get(0).containsKey("service_name")) {
                            services = cachedServicesList;
                            log.info("[getAdminUserDeviceServices] 从Redis缓存获取服务成功，用户ID: {}, 设备ID: {}, 服务: {}", 
                                userId, deviceId, services);
                        } else {
                            // 旧格式缓存，删除并重新获取
                            log.info("[getAdminUserDeviceServices] 检测到旧格式缓存，删除并重新获取，用户ID: {}, 设备ID: {}", userId, deviceId);
                            redisTemplate.delete(redisKey);
                        }
                    } catch (Exception e) {
                        // 解析失败，可能是旧格式，删除缓存
                        log.info("[getAdminUserDeviceServices] 缓存解析失败，删除缓存并重新获取，用户ID: {}, 设备ID: {}", userId, deviceId);
                        redisTemplate.delete(redisKey);
                    }
                }
                
                // 如果缓存被删除或不存在，从数据库获取
                if (services.isEmpty()) {
                    String sql = "SELECT id, service_identifier, service_name, description, service_value FROM iot_user_device_services WHERE user_id = ? AND device_id = ? AND deleted = 0 ORDER BY create_time";
                    services = jdbcTemplate.queryForList(sql, userId, deviceId);
                    
                    // 如果没有service_name，则生成默认值
                    for (Map<String, Object> service : services) {
                        if (service.get("service_name") == null || ((String) service.get("service_name")).trim().isEmpty()) {
                            String identifier = (String) service.get("service_identifier");
                            service.put("service_name", getServiceDisplayName(identifier));
                        }
                        if (service.get("description") == null || ((String) service.get("description")).trim().isEmpty()) {
                            String identifier = (String) service.get("service_identifier");
                            service.put("description", getServiceDescription(identifier));
                        }
                    }
                    
                    // 更新Redis缓存（缓存完整的服务信息）
                    if (!services.isEmpty()) {
                        redisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(services), 24, TimeUnit.HOURS);
                        log.info("[getAdminUserDeviceServices] Redis缓存更新成功，用户ID: {}, 设备ID: {}, 服务: {}", 
                            userId, deviceId, services);
                    }
                }
            } else {
                // 获取用户所有设备的服务
                String sql = "SELECT DISTINCT id, service_identifier, service_name, description, service_value FROM iot_user_device_services WHERE user_id = ? AND deleted = 0 ORDER BY service_identifier";
                services = jdbcTemplate.queryForList(sql, userId);
                
                // 如果没有service_name，则生成默认值
                for (Map<String, Object> service : services) {
                    if (service.get("service_name") == null || ((String) service.get("service_name")).trim().isEmpty()) {
                        String identifier = (String) service.get("service_identifier");
                        service.put("service_name", getServiceDisplayName(identifier));
                    }
                    if (service.get("description") == null || ((String) service.get("description")).trim().isEmpty()) {
                        String identifier = (String) service.get("service_identifier");
                        service.put("description", getServiceDescription(identifier));
                    }
                }
            }
            
            log.info("[getAdminUserDeviceServices] 获取用户设备服务成功，用户ID: {}, 设备ID: {}, 服务数量: {}", 
                userId, deviceId, services.size());
            return success(services);
            
        } catch (Exception e) {
            log.error("[getAdminUserDeviceServices] 获取用户设备服务异常，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            return CommonResult.error(500, "获取服务失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/thing/model/list")
    @Operation(summary = "获得设备物模型列表")
    @Parameter(name = "productId", description = "产品编号", required = true, example = "1024")
    @Parameter(name = "type", description = "功能类型", required = false, example = "2")
    public CommonResult<List<IotThingModelRespVO>> getDeviceThingModel(@RequestParam("productId") Long productId,
                                                                      @RequestParam(value = "type", required = false) Integer type) {
        log.info("[IotAppDeviceController] 获取设备物模型请求，产品ID: {}, 类型: {}", productId, type);
        
        try {
            IotThingModelListReqVO reqVO = new IotThingModelListReqVO();
            reqVO.setProductId(productId);
            if (type != null) {
                reqVO.setType(type);
            }
            
            List<IotThingModelDO> thingModels = thingModelService.getThingModelList(reqVO);
            List<IotThingModelRespVO> result = BeanUtils.toBean(thingModels, IotThingModelRespVO.class);
            
            log.info("[getDeviceThingModel] 获取设备物模型成功，产品ID: {}, 类型: {}, 数量: {}", 
                productId, type, result.size());
            return success(result);
            
        } catch (Exception e) {
            log.error("[getDeviceThingModel] 获取设备物模型异常，产品ID: {}, 类型: {}", productId, type, e);
            return CommonResult.error(500, "获取物模型失败：" + e.getMessage());
        }
    }

    /**
     * 清理设备相关的服务数据
     * 包括数据库记录和Redis缓存
     */
    private void cleanupDeviceServices(Long userId, Long deviceId) {
        try {
            log.info("[cleanupDeviceServices] 开始清理设备服务数据，用户ID: {}, 设备ID: {}", userId, deviceId);
            
            // 1. 软删除用户设备服务记录
            String deleteServicesSql = "UPDATE iot_user_device_services SET deleted = 1, update_time = NOW() WHERE user_id = ? AND device_id = ? AND deleted = 0";
            int servicesResult = jdbcTemplate.update(deleteServicesSql, userId, deviceId);
            log.info("[cleanupDeviceServices] 删除用户设备服务记录成功，用户ID: {}, 设备ID: {}, 影响记录数: {}", userId, deviceId, servicesResult);
            
            // 2. 清理Redis缓存中的设备服务信息
            try {
                String redisKey = String.format("iot:user:device:services:%d:%d", userId, deviceId);
                redisTemplate.delete(redisKey);
                log.info("[cleanupDeviceServices] Redis缓存删除成功，key: {}", redisKey);
            } catch (Exception redisError) {
                log.warn("[cleanupDeviceServices] Redis缓存删除失败，用户ID: {}, 设备ID: {}, 错误: {}", userId, deviceId, redisError.getMessage());
                // Redis删除失败不影响主流程
            }
            
            log.info("[cleanupDeviceServices] 设备服务数据清理完成，用户ID: {}, 设备ID: {}", userId, deviceId);
            
        } catch (Exception e) {
            log.error("[cleanupDeviceServices] 清理设备服务数据失败，用户ID: {}, 设备ID: {}", userId, deviceId, e);
            // 不抛出异常，避免影响主流程
        }
    }

    /**
     * 清理用户设备服务的Redis缓存
     */
    private void clearUserDeviceServicesCache(Long userId, Long deviceId) {
        try {
            String redisKey = String.format("iot:user:device:services:%d:%d", userId, deviceId);
            redisTemplate.delete(redisKey);
            log.info("[clearUserDeviceServicesCache] 清理Redis缓存成功，key: {}", redisKey);
        } catch (Exception e) {
            log.warn("[clearUserDeviceServicesCache] 清理Redis缓存失败，用户ID: {}, 设备ID: {}, 错误: {}", userId, deviceId, e.getMessage());
        }
    }

    @GetMapping("/getUserDeviceName/{deviceId}")
    @Operation(summary = "根据设备ID获取用户自定义设备名称")
    @TenantIgnore
    public CommonResult<String> getUserDeviceName(@PathVariable Long deviceId) {
        Long userId = SecurityFrameworkUtils.getLoginUserId();

        if (userId == null) {
            log.warn("用户未登录，操作失败");
            return CommonResult.error(401, "用户未登录");
        }
        try {
            String sql = "SELECT custom_device_name FROM iot_user_device WHERE user_id = ? AND device_id = ? AND deleted = 0";
            String customDeviceName = jdbcTemplate.queryForObject(sql, String.class, userId, deviceId);
            return success(customDeviceName);
        } catch (Exception e) {
            log.warn("获取用户设备名称失败，用户ID: {}, 设备ID: {}, 错误: {}", userId, deviceId, e.getMessage());
            return success(null);
        }
    }
}